/*
 * Protein.h
 *
 *  Created on: Jul 6, 2013
 *      Author: x
 */

#ifndef PROTEIN_H_
#define PROTEIN_H_

#include <vector>
#include <string>
#include "Microstate.h"
#include "Env.h"

namespace mcce {
class Residue;
class Conformer;

class Protein {
public:
	struct RESIDUE {
		size_t n;      /* Number of free confs on this residue */
		int on;
		int *conf;  /* idices of free confs */

		RESIDUE(): n(0), on(0), conf(0) {}
		~RESIDUE() {
			if (conf) delete[] conf;
		}
	};

	struct BIGLIST {
		size_t n;
		int *res;

		BIGLIST(): n(0), res(0) {}
		~BIGLIST() {
			if (res) delete[] res;
		}
	};
private:
	float eBase;       // energy of the fixed portion.
	float eFree;		// energy of free portion
	float eTotal;      // total energy of the protein.

	int *state;
//	std::vector<std::vector<float> > pairwise;
	// using array instead of vector for pairwise is faster
	float **pairwise;
//	std::vector<std::vector<int> > biglist;
	size_t n_free;
	BIGLIST *biglist;
	RESIDUE *free_res;

	std::vector<Residue> residues;
	Microstate mcState;    // microstate in the MC sampling.


	std::vector<Residue*> freeResidues;
	std::vector<Conformer*> freeConformers;

//	std::vector<Conformer*> conflist;
	size_t nTotalConf;
	Conformer **conflist;
public:
	static Env env;
	static void loadEnv();

	Protein();
	~Protein();

	std::vector<Residue>& getResidues() {
		return residues;
	}

	void setResidues(const std::vector<Residue>& residues) {
		this->residues = residues;
	}

	float calculateEFree();

	Protein& loadConfFromHead3(std::string fName);

	// for all the conformers, find the residue which each of them belongs to.
	void indexAllConf();

	Protein& adjustHead3Flag();

	Protein& loadConfOpp(std::string fName, float scale_ele=1.0, float scale_vdw=1.0);

	// calculate the base energy of the protein
	float calculateBase(float ph=7.0, float eh=0.0);

	float getEBase() const {
		return eBase;
	}

	void findResNeighbor(float threshold);

	void setGroupedFreeConf();

	Microstate& getMcState() {
		return mcState;
	}

	void setRandomMcState();

	int getNTotalConf() const {
		return nTotalConf;
	}

	Conformer** getConflist() const {
		return conflist;
	}
	// initial settings of MC sampling
	void setupMC(float ph=7.0, float eh=0.0);

	// initialize or reset the "state" member
	void setState();

	void mcSample(int cycles, float ph=7.0, float eh=0.0);

	void clearConfCounter();

	void reduceFreeRes();

	int getNumberOfFreeConf();

	void printConfInfo();

	void enumMstate();


	// find all the free residues and the free conformers in them
	void setFreeResConf();

	std::vector<Residue*>& getFreeResidues() {
		return freeResidues;
	}

	std::vector<Conformer*>& getFreeConformer() {
		return freeConformers;
	}

	// copy the occ value of a conformer to a vector mocc to save it.
	void saveConfOcc();
};

} /* namespace mcce */
#endif /* PROTEIN_H_ */
